package acs.timer;

import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;

import acs.collection.Params;
import acs.controller.MessageQueue;

public class SoftTimer {
	// active items
	private  ConcurrentLinkedQueue<TimerItem> itemRegistered = new ConcurrentLinkedQueue<TimerItem>();
	// item pool for reuse
	private  ConcurrentLinkedQueue<TimerItem> itemPool = new ConcurrentLinkedQueue<TimerItem>();
	private Timer checkTimer;
	private long checkInterval = 10;

	private static SoftTimer instance=new SoftTimer();
	public static SoftTimer getInstance() {
		return instance;
	}
	private SoftTimer() {
		init();
	}

	private void init() {
		checkTimer = new Timer();

		// The timer can not be scheduled after it's cancelled, so there, the repeat
		// mode is using
		this.checkTimer.schedule(new TimerTask() {
			@Override
			public void run() {
				check();
			}
		}, this.checkInterval, this.checkInterval);

	}

	static class TimerItem {
		long startTime;
		long delay;
		int event;
	}

	private void check() {
		long currentTime;
		Iterator<TimerItem> itr;

		currentTime = System.currentTimeMillis();
		itr = itemRegistered.iterator();

		while (itr.hasNext()) {
			TimerItem item = itr.next();

			if ((item != null) && (item.delay <= (currentTime - item.startTime))) {
				if (itemRegistered.remove(item)) {
					Params param = Params.build();

					MessageQueue.getInstance().putMessage(item.event, param);
					// push into pool for re-use
					itemPool.add(item);
				}
			}
		}
	}

	public void startTimer(long delay, int event) {
		TimerItem timerItem = itemPool.poll();
		if (timerItem == null) {
			timerItem = new TimerItem();
		}

		timerItem.startTime = System.currentTimeMillis();
		timerItem.delay = delay;
		timerItem.event = event;

		itemRegistered.add(timerItem);
	}
}
